home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / cagd_lib / sbzr_aux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-14  |  19.9 KB  |  506 lines

  1. /******************************************************************************
  2. * SBzr-Aux.c - Bezier surface auxilary routines.                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, July. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "cagd_loc.h"
  11.  
  12. /* Define some marcos to make some of the routines below look better. They  */
  13. /* calculate the index of the U, V point of the control mesh in Points.        */
  14. #define DERIVED_SRF(U, V)    CAGD_MESH_UV(DerivedSrf, U, V)
  15. #define RAISED_SRF(U, V)    CAGD_MESH_UV(RaisedSrf, U, V)
  16. #define SRF(U, V)        CAGD_MESH_UV(Srf, U, V)
  17.  
  18. static CagdSrfStruct *CnvrtBspline2BezierSrfAux(CagdSrfStruct *Srf);
  19.  
  20. /*****************************************************************************
  21. * DESCRIPTION:                                                               M
  22. * Given a Bezier surface - subdivides it into two sub-surfaces at the given  M
  23. * parametric value.                                                          M
  24. *   Returns pointer to first surface in a list of two subdivided surfaces.   M
  25. *                                                                            *
  26. * PARAMETERS:                                                                M
  27. *   Srf:      To subdivide at parameter value t.                             M
  28. *   t:        Parameter value to subdivide Srf at.                           M
  29. *   Dir:      Direction of subdivision. Either U or V.                       M
  30. *                                                                            *
  31. * RETURN VALUE:                                                              M
  32. *   CagdSrfStruct *:  A list of the two subdivided surfaces.                 M
  33. *                                                                            *
  34. * KEYWORDS:                                                                  M
  35. *   BzrSrfSubdivAtParam, subdivision, refinement                             M
  36. *****************************************************************************/
  37. CagdSrfStruct *BzrSrfSubdivAtParam(CagdSrfStruct *Srf,
  38.                    CagdRType t,
  39.                    CagdSrfDirType Dir)
  40. {
  41.     int Row, Col,
  42.     ULength = Srf -> ULength,
  43.     VLength = Srf -> VLength;
  44.     CagdCrvStruct *Crv, *LCrv, *RCrv;
  45.     CagdSrfStruct
  46.     *RSrf = BzrSrfNew(ULength, VLength, Srf ->PType),
  47.     *LSrf = BzrSrfNew(ULength, VLength, Srf ->PType);
  48.  
  49.     switch (Dir) {
  50.     case CAGD_CONST_U_DIR:
  51.         for (Row = 0; Row < VLength; Row++) {
  52.         Crv = BzrSrfCrvFromMesh(Srf, Row, CAGD_CONST_V_DIR);
  53.         LCrv = BzrCrvSubdivAtParam(Crv, t);
  54.         RCrv = LCrv -> Pnext;
  55.         CagdCrvToMesh(LCrv, Row, CAGD_CONST_V_DIR, LSrf);
  56.         CagdCrvToMesh(RCrv, Row, CAGD_CONST_V_DIR, RSrf);
  57.  
  58.         CagdCrvFree(Crv);
  59.         CagdCrvFree(LCrv);
  60.         CagdCrvFree(RCrv);
  61.         }
  62.         break;
  63.     case CAGD_CONST_V_DIR:
  64.         for (Col = 0; Col < ULength; Col++) {
  65.         Crv = BzrSrfCrvFromMesh(Srf, Col, CAGD_CONST_U_DIR);
  66.         LCrv = BzrCrvSubdivAtParam(Crv, t);
  67.         RCrv = LCrv -> Pnext;
  68.         CagdCrvToMesh(LCrv, Col, CAGD_CONST_U_DIR, LSrf);
  69.         CagdCrvToMesh(RCrv, Col, CAGD_CONST_U_DIR, RSrf);
  70.  
  71.         CagdCrvFree(Crv);
  72.         CagdCrvFree(LCrv);
  73.         CagdCrvFree(RCrv);
  74.         }
  75.         break;
  76.     default:
  77.         CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  78.         break;
  79.     }
  80.  
  81.     LSrf -> Pnext = RSrf;
  82.     return LSrf;
  83. }
  84.  
  85. /*****************************************************************************
  86. * DESCRIPTION:                                                               M
  87. * Returns a new Bezier surface, identical to the original but with one       M
  88. * degree higher, in the requested direction Dir.                             M
  89. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:   M
  90. *               i        k-i                         V
  91. * Q(0) = P(0), Q(i) = --- P(i-1) + (---) P(i), Q(k) = P(k-1).             V
  92. *               k         k                         V
  93. * This is applied to all rows/cols of the surface.                 M
  94. *                                                                            *
  95. * PARAMETERS:                                                                M
  96. *   Srf:        To raise it degree by one.                                   M
  97. *   Dir:        Direction to degree raise. Either U or V.                    M
  98. *                                                                            *
  99. * RETURN VALUE:                                                              M
  100. *   CagdSrfStruct *:  A surface with one degree higher in direction Dir,     M
  101. *                     representing the same geometry as Srf.             M
  102. *                                                                            *
  103. * KEYWORDS:                                                                  M
  104. *   BzrSrfDegreeRaise, degree raising                                        M
  105. *****************************************************************************/
  106. CagdSrfStruct *BzrSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  107. {
  108.     CagdBType
  109.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  110.     int i, j, Row, Col,
  111.     ULength = Srf -> ULength,
  112.     VLength = Srf -> VLength,
  113.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  114.     CagdSrfStruct
  115.     *RaisedSrf = NULL;
  116.  
  117.     switch (Dir) {
  118.     case CAGD_CONST_U_DIR:
  119.         RaisedSrf = BzrSrfNew(ULength, VLength + 1, Srf -> PType);
  120.  
  121.         for (Col = 0; Col < ULength; Col++) {
  122.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(0). */
  123.             RaisedSrf -> Points[j][RAISED_SRF(Col, 0)] =
  124.                Srf -> Points[j][SRF(Col, 0)];
  125.  
  126.         for (i = 1; i < VLength; i++)                /* Q(i). */
  127.             for (j = IsNotRational; j <= MaxCoord; j++)
  128.             RaisedSrf -> Points[j][RAISED_SRF(Col, i)] =
  129.                 Srf -> Points[j][SRF(Col, i - 1)] *
  130.                                  (i / ((CagdRType) VLength)) +
  131.                 Srf -> Points[j][SRF(Col, i)] *
  132.                      ((VLength - i) / ((CagdRType) VLength));
  133.  
  134.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(k). */
  135.             RaisedSrf -> Points[j][RAISED_SRF(Col, VLength)] =
  136.             Srf -> Points[j][SRF(Col, VLength - 1)];
  137.             }
  138.         break;
  139.     case CAGD_CONST_V_DIR:
  140.         RaisedSrf = BzrSrfNew(ULength + 1, VLength, Srf -> PType);
  141.  
  142.         for (Row = 0; Row < VLength; Row++) {
  143.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(0). */
  144.             RaisedSrf -> Points[j][RAISED_SRF(0, Row)] =
  145.                Srf -> Points[j][SRF(0, Row)];
  146.  
  147.         for (i = 1; i < ULength; i++)                /* Q(i). */
  148.             for (j = IsNotRational; j <= MaxCoord; j++)
  149.             RaisedSrf -> Points[j][RAISED_SRF(i, Row)] =
  150.                 Srf -> Points[j][SRF(i - 1, Row)] *
  151.                                  (i / ((CagdRType) ULength)) +
  152.                 Srf -> Points[j][SRF(i, Row)] *
  153.                          ((ULength - i) / ((CagdRType) ULength));
  154.  
  155.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(k). */
  156.             RaisedSrf -> Points[j][RAISED_SRF(ULength, Row)] =
  157.             Srf -> Points[j][SRF(ULength - 1, Row)];
  158.         }
  159.         break;
  160.     default:
  161.         CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  162.         break;
  163.     }
  164.  
  165.     return RaisedSrf;
  166. }
  167.  
  168. /*****************************************************************************
  169. * DESCRIPTION:                                                               M
  170. * Returns a new surface equal to the given surface, differentiated once in   M
  171. * the direction Dir.                                 M
  172. *   Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then: M
  173. * Q(i) = (k - 1) * (P(i+1) - P(i)), i = 0 to k-2.                 V
  174. * This is applied to all rows/cols of the surface.                 M
  175. *                                                                            *
  176. * PARAMETERS:                                                                M
  177. *   Srf:        To differentiate.                                            M
  178. *   Dir:        Direction of differentiation. Either U or V.                 M
  179. *                                                                            *
  180. * RETURN VALUE:                                                              M
  181. *   CagdSrfStruct *:   Differentiated surface.                               M
  182. *                                                                            *
  183. * KEYWORDS:                                                                  M
  184. *   BzrSrfDerive, derivatives, partial derivatives                           M
  185. *****************************************************************************/
  186. CagdSrfStruct *BzrSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  187. {
  188.     CagdBType
  189.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  190.     int i, j, Row, Col,
  191.     ULength = Srf -> ULength,
  192.     VLength = Srf -> VLength,
  193.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  194.     CagdSrfStruct
  195.         *DerivedSrf = NULL;
  196.  
  197.     if (!IsNotRational)
  198.     return BzrSrfDeriveRational(Srf, Dir);
  199.  
  200.     switch (Dir) {
  201.     case CAGD_CONST_U_DIR:
  202.         DerivedSrf = BzrSrfNew(MAX(ULength - 1, 1), VLength, Srf -> PType);
  203.  
  204.         for (Row = 0; Row < VLength; Row++)
  205.         for (i = 0; i < MAX(ULength - 1, 1); i++)
  206.             for (j = IsNotRational; j <= MaxCoord; j++)
  207.             DerivedSrf -> Points[j][DERIVED_SRF(i, Row)] =
  208.                 ULength < 2 ? 0.0
  209.                     : (ULength - 1) *
  210.                        (Srf -> Points[j][SRF(i + 1, Row)] -
  211.                         Srf -> Points[j][SRF(i, Row)]);
  212.         break;
  213.     case CAGD_CONST_V_DIR:
  214.         DerivedSrf = BzrSrfNew(ULength, MAX(VLength - 1, 1), Srf -> PType);
  215.  
  216.         for (Col = 0; Col < ULength; Col++)
  217.         for (i = 0; i < MAX(VLength - 1, 1); i++)
  218.             for (j = IsNotRational; j <= MaxCoord; j++)
  219.             DerivedSrf -> Points[j][DERIVED_SRF(Col, i)] =
  220.                 VLength < 2 ? 0.0
  221.                     : (VLength - 1) *
  222.                        (Srf -> Points[j][SRF(Col, i + 1)] -
  223.                         Srf -> Points[j][SRF(Col, i)]);
  224.         break;
  225.     default:
  226.         CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  227.         break;
  228.     }
  229.  
  230.     return DerivedSrf;
  231. }
  232.  
  233. /*****************************************************************************
  234. * DESCRIPTION:                                                               M
  235. * Evaluates the unit tangent to a surface at a given parametric location     M
  236. ( u, v) and given direction Dir.                                             M
  237. *                                                                            *
  238. * PARAMETERS:                                                                M
  239. *   Srf:        Bezier surface to evaluate tangent vector for.               M
  240. *   u, v:       Parametric location of required unit tangent.                M
  241. *   Dir:        Direction of tangent vector. Either U or V.                  M
  242. *                                                                            *
  243. * RETURN VALUE:                                                              M
  244. *   CagdVecStruct *:  A pointer to a static vector holding the unit tangent  M
  245. *                     information.                                           M
  246. *                                                                            *
  247. * KEYWORDS:                                                                  M
  248. *   BzrSrfTangent, tangent                                                   M
  249. *****************************************************************************/
  250. CagdVecStruct *BzrSrfTangent(CagdSrfStruct *Srf,
  251.                  CagdRType u,
  252.                  CagdRType v,
  253.                  CagdSrfDirType Dir)
  254. {
  255.     CagdVecStruct
  256.     *Tangent = NULL;
  257.     CagdCrvStruct *Crv;
  258.  
  259.     switch (Dir) {
  260.     case CAGD_CONST_V_DIR:
  261.         Crv = BzrSrfCrvFromSrf(Srf, v, Dir);
  262.         Tangent = BzrCrvTangent(Crv, u);
  263.         CagdCrvFree(Crv);
  264.         break;
  265.     case CAGD_CONST_U_DIR:
  266.         Crv = BzrSrfCrvFromSrf(Srf, u, Dir);
  267.         Tangent = BzrCrvTangent(Crv, v);
  268.         CagdCrvFree(Crv);
  269.         break;
  270.     default:
  271.         CAGD_FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  272.         break;
  273.     }
  274.  
  275.     return Tangent;
  276. }
  277.  
  278. /*****************************************************************************
  279. * DESCRIPTION:                                                               M
  280. * Evaluate the unit normal of a surface at a given parametric location.      M
  281. *   If we fail to compute the normal at given location we retry by moving a  M
  282. * tad.                                                                       M
  283. *                                                                            *
  284. * PARAMETERS:                                                                M
  285. *   Srf:        Bezier surface to evaluate normal vector for.                M
  286. *   u, v:       Parametric location of required unit normal.                 M
  287. *                                                                            *
  288. * RETURN VALUE:                                                              M
  289. *   CagdVecStruct *:  A pointer to a static vector holding the unit normal   M
  290. *                     information.                                           M
  291. *                                                                            *
  292. * KEYWORDS:                                                                  M
  293. *   BzrSrfNormal, normal                                                     M
  294. *****************************************************************************/
  295. CagdVecStruct *BzrSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
  296. {
  297.     static CagdVecStruct Normal;
  298.     CagdVecStruct *V, T1, T2;
  299.  
  300.     V = BzrSrfTangent(Srf, u, v, CAGD_CONST_U_DIR);
  301.     if (CAGD_LEN_VECTOR(*V) < EPSILON)
  302.     V = BzrSrfTangent(Srf,
  303.               u > 0.5 ? u - EPSILON : u + EPSILON,
  304.               v > 0.5 ? v - EPSILON : v + EPSILON,
  305.               CAGD_CONST_U_DIR);
  306.     CAGD_COPY_VECTOR(T1, *V);
  307.  
  308.     V = BzrSrfTangent(Srf, u, v, CAGD_CONST_V_DIR);
  309.     if (CAGD_LEN_VECTOR(*V) < EPSILON)
  310.     V = BzrSrfTangent(Srf,
  311.               u > 0.5 ? u - EPSILON : u + EPSILON,
  312.               v > 0.5 ? v - EPSILON : v + EPSILON,
  313.               CAGD_CONST_V_DIR);
  314.     CAGD_COPY_VECTOR(T2, *V);
  315.  
  316.     /* The normal is the cross product of T1 and T2: */
  317.     Normal.Vec[0] = T1.Vec[1] * T2.Vec[2] - T1.Vec[2] * T2.Vec[1];
  318.     Normal.Vec[1] = T1.Vec[2] * T2.Vec[0] - T1.Vec[0] * T2.Vec[2];
  319.     Normal.Vec[2] = T1.Vec[0] * T2.Vec[1] - T1.Vec[1] * T2.Vec[0];
  320.  
  321.     CAGD_NORMALIZE_VECTOR(Normal);            /* Normalize the vector. */
  322.  
  323.     return &Normal;
  324. }
  325.  
  326. /*****************************************************************************
  327. * DESCRIPTION:                                                               M
  328. * Converts a bezier surface into a Bspline surface by adding open end        M
  329. * knot vector with no interior knots.                                        M
  330. *                                                                            *
  331. * PARAMETERS:                                                                M
  332. *   Srf:       Bezier surface to convert to a Bspline surface.               M
  333. *                                                                            *
  334. * RETURN VALUE:                                                              M
  335. *   CagdSrfStruct *:  A Bspline surface representing same geometry as Srf.   M
  336. *                                                                            *
  337. * KEYWORDS:                                                                  M
  338. *   CnvrtBezier2BsplineSrf, conversion                                       M
  339. *****************************************************************************/
  340. CagdSrfStruct *CnvrtBezier2BsplineSrf(CagdSrfStruct *Srf)
  341. {
  342.     CagdSrfStruct *BspSrf;
  343.  
  344.     if (Srf -> GType != CAGD_SBEZIER_TYPE) {
  345.     CAGD_FATAL_ERROR(CAGD_ERR_WRONG_SRF);
  346.     return NULL;
  347.     }
  348.  
  349.     BspSrf = CagdSrfCopy(Srf);
  350.  
  351.     BspSrf -> UOrder = BspSrf -> ULength;
  352.     BspSrf -> VOrder = BspSrf -> VLength;
  353.     BspSrf -> UKnotVector = BspKnotUniformOpen(BspSrf -> ULength,
  354.                             BspSrf -> UOrder, NULL);
  355.     BspSrf -> VKnotVector = BspKnotUniformOpen(BspSrf -> VLength,
  356.                             BspSrf -> VOrder, NULL);
  357.     BspSrf -> GType = CAGD_SBSPLINE_TYPE;
  358.     return BspSrf;
  359. }
  360.  
  361. /*****************************************************************************
  362. * DESCRIPTION:                                                               M
  363. * Convert a Bspline surface into a set of Bezier surfaces by subdiving the   M
  364. * Bspline surface at all its internal knots.                     M
  365. *   Returned is a list of Bezier surface.                     M
  366. *                                                                            *
  367. * PARAMETERS:                                                                M
  368. *   Srf:       Bspline surface to convert to a Bezier surface.               M
  369. *                                                                            *
  370. * RETURN VALUE:                                                              M
  371. *   CagdSrfStruct *:  A list of Bezier surfaces representing same geometry   M
  372. *                     as Srf.                             M
  373. *                                                                            *
  374. * KEYWORDS:                                                                  M
  375. *   CnvrtBezier2BsplineSrf, conversion                                       M
  376. *****************************************************************************/
  377. CagdSrfStruct *CnvrtBspline2BezierSrf(CagdSrfStruct *Srf)
  378. {
  379.     CagdBType
  380.     NewSrf = FALSE;
  381.     int i, UOrder, ULength;
  382.     CagdRType LastT, *UKnotVector;
  383.     CagdSrfStruct *BezierSrfsAux, *TSrf, *OrigSrf,
  384.     *BezierSrfs = NULL;
  385.  
  386.     if (Srf -> GType != CAGD_SBSPLINE_TYPE) {
  387.     CAGD_FATAL_ERROR(CAGD_ERR_WRONG_SRF);
  388.     return NULL;
  389.     }
  390.  
  391.     if (!BspSrfHasOpenEC(Srf)) {
  392.     Srf = BspSrfOpenEnd(Srf);
  393.     NewSrf = TRUE;
  394.     }
  395.     UOrder = Srf -> UOrder;
  396.     ULength = Srf -> ULength;
  397.     UKnotVector = Srf -> UKnotVector;
  398.     OrigSrf = Srf;
  399.  
  400.     for (i = ULength - 1, LastT = UKnotVector[ULength]; i >= UOrder; i--) {
  401.         CagdRType
  402.             t = UKnotVector[i];
  403.             
  404.     if (!APX_EQ(LastT, t)) {
  405.             CagdSrfStruct
  406.             *Srfs = BspSrfSubdivAtParam(Srf, t, CAGD_CONST_U_DIR);
  407.  
  408.             if (Srf != OrigSrf)
  409.                 CagdSrfFree(Srf);
  410.  
  411.         BezierSrfsAux = CnvrtBspline2BezierSrfAux(Srfs -> Pnext);
  412.         for (TSrf = BezierSrfsAux;
  413.          TSrf -> Pnext != NULL;
  414.          TSrf = TSrf -> Pnext);
  415.         TSrf -> Pnext = BezierSrfs;
  416.         BezierSrfs = BezierSrfsAux;
  417.         CagdSrfFree(Srfs -> Pnext);
  418.  
  419.             Srf = Srfs;
  420.             Srf -> Pnext = NULL;
  421.         }
  422.     }
  423.  
  424.     if (Srf == OrigSrf)
  425.     BezierSrfs = CnvrtBspline2BezierSrfAux(Srf);
  426.     else {
  427.     BezierSrfsAux = CnvrtBspline2BezierSrfAux(Srf);
  428.     for (TSrf = BezierSrfsAux;
  429.          TSrf -> Pnext != NULL;
  430.          TSrf = TSrf -> Pnext);
  431.     TSrf -> Pnext = BezierSrfs;
  432.     BezierSrfs = BezierSrfsAux;
  433.  
  434.     CagdSrfFree(Srf);
  435.     }
  436.  
  437.     if (NewSrf)
  438.     CagdSrfFree(Srf);
  439.  
  440.     return BezierSrfs;
  441. }
  442.  
  443. /*****************************************************************************
  444. * DESCRIPTION:                                                               *
  445. * Auxiliary function of CnvrtBspline2BezierSrf. Does the other V direction's *
  446. * subdivision.                                                                 *
  447. *                                                                            *
  448. * PARAMETERS:                                                                *
  449. *   Srf:       To subdivide at all its interior knots in the V direction.    *
  450. *                                                                            *
  451. * RETURN VALUE:                                                              *
  452. *   CagdSrfStruct *:  A list of Bezier surfaces representing same geometry   *
  453. *                     as Srf.                             *
  454. *****************************************************************************/
  455. static CagdSrfStruct *CnvrtBspline2BezierSrfAux(CagdSrfStruct *Srf)
  456. {
  457.     int i,
  458.     VOrder = Srf -> VOrder,
  459.     VLength = Srf -> VLength;
  460.     CagdRType LastT,
  461.     *VKnotVector = Srf -> VKnotVector;
  462.     CagdSrfStruct
  463.     *BezierSrfs = NULL,
  464.     *OrigSrf = Srf;
  465.  
  466.     for (i = VLength - 1, LastT = VKnotVector[VLength]; i >= VOrder; i--) {
  467.         CagdRType
  468.             t = VKnotVector[i];
  469.             
  470.     if (!APX_EQ(LastT, t)) {
  471.             CagdSrfStruct
  472.             *Srfs = BspSrfSubdivAtParam(Srf, t, CAGD_CONST_V_DIR);
  473.  
  474.             if (Srf != OrigSrf)
  475.                 CagdSrfFree(Srf);
  476.  
  477.             Srfs -> Pnext -> Pnext = BezierSrfs;
  478.         BezierSrfs = Srfs -> Pnext;
  479.  
  480.             Srf = Srfs;
  481.             Srf -> Pnext = NULL;
  482.         }
  483.     }
  484.  
  485.     if (Srf == OrigSrf) {
  486.     /* No interior knots in this surface - just copy it: */
  487.         BezierSrfs = CagdSrfCopy(Srf);
  488.     }
  489.     else {
  490.         Srf -> Pnext = BezierSrfs;
  491.         BezierSrfs = Srf;
  492.     }
  493.  
  494.     for (Srf = BezierSrfs; Srf != NULL; Srf = Srf -> Pnext) {
  495.         Srf -> GType = CAGD_SBEZIER_TYPE;
  496.     IritFree((VoidPtr) Srf -> UKnotVector);
  497.     IritFree((VoidPtr) Srf -> VKnotVector);
  498.     Srf -> UKnotVector = NULL;
  499.     Srf -> VKnotVector = NULL;
  500.     }
  501.     
  502.     return BezierSrfs;
  503. }
  504.  
  505.  
  506.